<html xmlns="http://www.w3.org/1999/xhtml" id="rpc-javarpc">
<head>
    <title>JavaRPC</title>
</head>

<body>
<warning>
This feature works in proxied applications only.  It does not work in serverless applications.
</warning>
<h1>JavaRPC</h1>

<p>JavaRPC is a feature that allows server-side Java objects and methods to be
accessed from a client application. The &lt;javarpc&gt; element is used to
declare a JavaRPC object in LZX. JavaRPC is part of the Laszlo RPC family and
shares similar APIs with SOAP and XML-RPC. See the RPC chapter for details.</p>

<!-- ========================================================= -->
<!-- javarpc                                                   -->
<!-- ========================================================= -->
<h2>&lt;javarpc&gt;</h2>

<p>Declare a javarpc element to create a JavaRPC object in LZX. The classname
attribute specifies what class javarpc represents. To use a class, place it in
WEB-INF/classes or, if it exists in a jar, in WEB-INF lib. This will ensure that
the class is accessible to the LPS.</p>

<example extract="false">
&lt;javarpc classname="..."
     attributename="..."
     scope="[session|webapp|none]"
     loadoption="[loadcreate|loadonly|create]"
     createargs="..."
     objectreturntype="[pojo|javabean]"
     autoload="[true|false]"
     secure="[true|false]"
     secureport="..."&gt;
</example>

<h2>Attributes</h2>

<p><dfn>classname</dfn>: (String) the remote java class to instantiate in the
server, or if scope is 'none', the static stub to return to the client
associated to the classname. <b>This is a required attribute.</b></p>

<p><dfn>attributename</dfn>: (String) the key to use for the server-side object
(see scope attribute). Attributename (or name) is required if scope is 'session'
or 'webapp'. <b>Defaults to the name attribute of this object.</b></p>

<p><dfn>scope</dfn>: (String) one of 'session', 'webapp', or 'none'. Session
scope means that the server object will be saved in a session attribute (see
javax.servlet.http.HttpSession). If scope is webapp, the server object is saved
in a web application context (see javax.servlet.ServletContext). For session and
webapp scopes, client-side remote methods will always invoke the samve saved
server objects. The objects are saved in a java.util.Map that is placed in an
attribute called "__lzobj". The map key for the object is the
<tt>attributename</tt> of the client-side javarpc object. If scope is none, no
object is saved in the server and only public static methods are defined in the
client-side javarpc object. <b>This is a required attribute.</b></p>

<p><dfn>loadoption</dfn>: (String) one of 'loadcreate', 'loadonly', or
'create'. Loadcreate tries to load javarpc object if it exists in the server,
else it creates it before loading. 'Loadonly' will only load object if it
exists, else an error is returned. 'Create' will always create the object in the
server. <b>Default is 'loadcreate'.</b></p>

<p><dfn>createargs</dfn>: (Array) valid only when loadoption='loadcreate' or
loadoption='create'. The array consists of parameters to construct server-side
object, for example [1, 'mystring', 1.45] would instantiate an object using a
constructor that takes an integer, a string, and a double. <b>Default is
null.</b></p>

<p><dfn>objectreturntype</dfn>: (String) one of 'pojo' or 'javabean'. If an
object is returned from the server, 'pojo' will return only the public member
values of that object and 'javabean' will return member values for members that
have corresponding getters. See <b>examples/javarpc/returnpojo.lzx</b> and
<b>examples/javarpc/returnjavabean.lzx</b> for usage example.</p>

<p><dfn>autoload</dfn>: (Boolean) if true, calls to load client proxy during
init stage. If false, the proxy must be loaded using the load() method.
<b>Default is true.</b></p>

<p><dfn>secure</dfn>: (Boolean) if true, creates a secure HTTPS connection
between the client and LPS. Also see secureport below. <b>Default is
false.</b></p>

<p><dfn>secureport</dfn>: (Number) valid only when secure attribute is set to
true. The secure port to use. There is no client-side default. Most servers use
port 443 as the default HTTPS port.</p>

<h3>Read-only properties</h3>

<p><dfn>proxy</dfn>: (Object) this is the object containing function stubs. It
is created by calling load() (which happens during init if autoload is true). If
scope is session or webapp, proxy contains all public methods described in the
server class (see classname attribute). If scope is none, proxy contains all
public static methods described in the server class. Note that proxy is not
defined until the onload event is sent, thus function stubs cannot be invoked
until onload. Each function stub requires two arguments: an array of parameters
and delegate. You can unload the proxy (i.e., set to null) by calling the
unload() method. Calling unload will also remove the server-side object if scope
is session or webapp. See the proxy section in the RPC chapter for details.</p>

<!-- ============================================================ -->

<h2>Events</h2>

<p>Note: event handler methods must be declared in the body of
&lt;javarpc&gt;. Attribute event handlers will not work.</p>

<p><dfn>onload</dfn>: this event is triggered when the proxy is returned to the
client.</p>

<p><dfn>onunload</dfn>: this event is triggered when the proxy is unloaded from
the client.</p>

<p><dfn>ondata</dfn>: this event is triggered when a declared &lt;remotecall&gt;
doesn't handle its ondata events. See the &lt;remotecall&gt; section for
details.</p>

<p><dfn>onerror</dfn>: this event is triggered if there was a problem loading or
unloading the stub, or if a declared &lt;remotecall&gt; didn't handle its
onerror event. See the &lt;remotecall&gt; section in the RPC chapter for
details.</p>

<!-- ============================================================ -->

<h2>Methods</h2>

<!-- ============================================================ -->

<h3>load()</h3>

<p>Load() is responsible for setting up the proxy property. When loading a
session scoped or webapp scoped object, a tuple of arguments may be passed in to
instantiate the server-side java object using the createargs attribute.
Createargs is an array of values and must match the server-side parameter
signature of the constructor. When the call returns, an onload event is sent and
the proxy will contain function stubs that mirror the public methods in the Java
class specified.</p>

<example title="Loading an object">
&lt;canvas debug="true"&gt;
 
    &lt;debug x="100" y="10" height="275" /&gt;

    &lt;!-- The security describes what classes are accessible or are allowed to be
         instantiated in the server. See the security section in this chapter
         for more information. --&gt;
    &lt;security&gt;
        &lt;allow&gt;
            &lt;pattern&gt;^examples\.ConstructExample&lt;/pattern&gt;
        &lt;/allow&gt;
    &lt;/security&gt;

    &lt;!-- See $LPS_HOME/WEB-INF/classes/ConstructExample.java for java
        source. --&gt;
    &lt;javarpc name="ce" scope="session" autoload="false"
             classname="examples.ConstructExample"
             createargs="[1, 'a string', 1.45]"&gt;

        &lt;method event="onerror" args="err"&gt;
            Debug.write("----------");
            Debug.write("onerror:", err)
        &lt;/method&gt;

        &lt;method event="onload"&gt;
            Debug.write("----------");
            Debug.write("constructed with", this.createargs);
            Debug.write(this.proxy);
        &lt;/method&gt;

    &lt;/javarpc&gt;
    
    &lt;simplelayout inset="10" spacing="5" /&gt;

    &lt;button x="10" text="construct"&gt;
        &lt;method event="onclick"&gt;
            canvas.ce.load();
        &lt;/method&gt;
    &lt;/button&gt;

    &lt;button x="10" text="getinfo"&gt;
        &lt;method event="onclick"&gt;
            this.getInfo.invoke();
        &lt;/method&gt;

        &lt;remotecall funcname="getInfo" remotecontext="$once{canvas.ce}"&gt;
            &lt;method event="ondata" args="res"&gt;
                Debug.write("----------");
                Debug.write("method:", this.name)
                Debug.write("return type:", typeof(res))
                Debug.write("return value:", res);
            &lt;/method&gt;
        &lt;/remotecall&gt;
    &lt;/button&gt;
&lt;/canvas&gt;
</example>

<p>The Java source for the previous example can be found in the
<tt>$LPS_HOME/WEB-INF/classes/examples</tt> directory. Here's what it looks
like:</p>

<example extract="false">
package examples;

public class ConstructExample {

    int mInt = 0;
    String mString = "";
    double mDouble = 0.0;

    public ConstructExample(int i) {
        mInt = i;
    }

    public ConstructExample(int i, String s, double d) {
        mInt = i;
        mString = s;
        mDouble = d;
    }

    public String getInfo() {
        return "int: " + mInt + "\n"
            + "string: " + mString + "\n"
            + "double: " + mDouble + "\n";
    }
}
</example>

<p>See RPC chapter for information on remotecall and other details about the
load() method.</p>

<!-- ============================================================ -->

<h3>unload()</h3>

<p>This method unloads the proxy from the RPC object and sets it to null. Also,
the associated java object is removed from the server-side map. When the call
returns, an onunload event is sent.</p>

<p><b>unload() implementation in javarpc.lzx</b></p>

<example>
&lt;canvas debug="true" height="300"&gt;
 
    &lt;debug x="100" y="10" height="275" /&gt;

    &lt;security&gt;
        &lt;allow&gt;
            &lt;pattern&gt;^examples\.ConstructExample&lt;/pattern&gt;
        &lt;/allow&gt;
    &lt;/security&gt;

    &lt;!-- See $LPS_HOME/WEB-INF/classes/ConstructExample.java for java
        source. --&gt;
    &lt;javarpc name="ce" scope="session" classname="examples.ConstructExample"
             createargs="[1, 'a string', 1.45]"&gt;

        &lt;method event="onerror" args="err"&gt;
            Debug.write("onerror:", err)
        &lt;/method&gt;

        &lt;method event="onload"&gt;
            Debug.write("loaded proxy:", this.proxy);
        &lt;/method&gt;

        &lt;method event="onunload"&gt;
            Debug.write("unloaded proxy:", this.proxy);
        &lt;/method&gt;

    &lt;/javarpc&gt;
    
    &lt;simplelayout spacing="10" /&gt;

    &lt;button text="load" onclick="canvas.ce.load()" /&gt;

    &lt;button text="unload" onclick="canvas.ce.unload()" /&gt;

    &lt;button text="proxy" onclick="Debug.write('proxy is', canvas.ce.proxy)" /&gt;

&lt;/canvas&gt;
</example>


<h2>Security</h2>

<p>Java classes used in an application must be declared in a security
element. Classes not defined in a security element are not allowed to be
accessed or instantiated. The format of the security element looks like:</p>

<example extract="false">
&lt;security&gt;
    &lt;allow&gt;
        &lt;pattern&gt;CLASS1&lt;/pattern&gt;
        &lt;pattern&gt;CLASS2&lt;/pattern&gt;
        ...
        &lt;pattern&gt;CLASSN&lt;/pattern&gt;
    &lt;/allow&gt;
&lt;/security&gt;
</example>

<p>Each &lt;pattern&gt; is a regular expression.</p>

<example extract="false" 
         title="Allow classes that start with org.openlaszlo">
&lt;security&gt;
    &lt;allow&gt;
        &lt;pattern&gt;^org\.openlaszlo&lt;/pattern&gt;
    &lt;/allow&gt;
&lt;/security&gt;
</example>

<p>A javarpc object who's class is not declared in a security tag will result in
a load error.</p>


<h2>Type Mapping</h2>

<p>This section describes how types are mapped from JavaScript function stub
parameters to Java method parameter and from Java return type to JavaScript
return type.</p>

<h3>Type mapping of parameters from JavaScript to Java</h3>

<p>
<table border="1">
<tr><th>JavaScript data type</th><th>Parameter types expected by java method</th></tr>
<tr><td>Number (int)</td><td>int</td></tr>
<tr><td>Number (double)*</td><td>double</td></tr>
<tr><td>LzRPC.DoubleWrapper</td><td>double</td></tr>
<tr><td>Boolean</td><td>boolean</td></tr>
<tr><td>Array</td><td>Vector</td></tr>
<tr><td>Object</td><td>Hashtable</td></tr>
</table>
</p>

<p>* Any floating point number with a zero decimal value is considered to be an
integer, i.e., 1.0 is really 1. Use LzRPC.DoubleWrapper to ensure a number is
considered a double. For example:</p>

<example extract="false">
    // assume myrpc is a javarpc object and myrpc.proxy.myMethod is a function
    // that expects a single double as a parameter
    var mydouble = new LzRPC.DoubleWrapper(1.0);
    myrpc.proxy.myMethod([ mydouble ], new LzDelegate(...));
</example>

<p>LzRPC can be found in <tt>$LPS_HOME/lps/components/rpc/library/LzRPC.js</tt>.</p>

<example title="Passing different parameter types">
&lt;canvas debug="true" height="300" width="800"&gt;
 
    &lt;debug x="250" y="10" width="500" height="275" /&gt;

    &lt;security&gt;
        &lt;allow&gt;
            &lt;pattern&gt;^examples\.TypesExample&lt;/pattern&gt;
        &lt;/allow&gt;
    &lt;/security&gt;

    &lt;!-- See WEB-INF/classes/TypesExample.java for java source. --&gt;
    &lt;javarpc name="types_example_rpc" scope="none" classname="examples.TypesExample"&gt;

        &lt;method event="onload"&gt;
            // Set buttons visible only after JavaRPC object loads
            canvas.buttons.setAttribute('visible', true);
        &lt;/method&gt;

        &lt;method event="ondata" args="res"&gt;
            Debug.write('(types ondata) response is:', res);
        &lt;/method&gt;

        &lt;method event="onerror" args="errmsg"&gt;
            Debug.write('(types onerror) error:', errmsg);
        &lt;/method&gt;

        &lt;!-- Declaratively pass an integer. --&gt;
        &lt;remotecall funcname="passInteger"&gt;
            &lt;param value="42" /&gt;
        &lt;/remotecall&gt;

        &lt;!-- Declaratively pass a double. Note that we name this function pd1
             because we have multiple remotecall declarations that call
             passDouble but with different parameters. --&gt;
        &lt;remotecall name="pd1" funcname="passDouble"&gt;
            &lt;param value="42.1" /&gt;
        &lt;/remotecall&gt;

        &lt;!-- Declaratively pass a double with 0 decimal. The 0 decimal will
             truncate and the number will become an integer type when it reaches
             the server. This call will fail. --&gt;
        &lt;remotecall name="pd2" funcname="passDouble"&gt;
            &lt;param value="42.0" /&gt;
        &lt;/remotecall&gt;

        &lt;!-- Declaratively pass a double with 0 decimal. Wrapping the double in
             DoubleWrapper will ensure the value will remain a double when
             reaching the server. --&gt;
        &lt;remotecall name="pd3" funcname="passDouble"&gt;
            &lt;param&gt; 
                &lt;method name="getValue"&gt;
                    return new LzRPC.DoubleWrapper(42.0);
                &lt;/method&gt;
            &lt;/param&gt;
        &lt;/remotecall&gt;

    &lt;/javarpc&gt;

    
    &lt;view name="buttons" visible="false" layout="spacing: 10" &gt;

        &lt;button text="pass integer"
                onclick="types_example_rpc.passInteger.invoke()" /&gt;

        &lt;button text="pass double"
                onclick="types_example_rpc.pd1.invoke()" /&gt;

        &lt;button text="pass double (will fail)"
                onclick="types_example_rpc.pd2.invoke()" /&gt;

        &lt;button text="pass double w/LzRPC.DoubleWrapper" 
                onclick="types_example_rpc.pd3.invoke()" /&gt;

        &lt;button text="pass boolean" onclick="this.passBoolean.invoke()"&gt;
            &lt;!-- This is a way to declare a remotecall closer to where it's being
                 used. The remotecontext must be set. --&gt;
            &lt;remotecall funcname="passBoolean" 
                        remotecontext="$once{ types_example_rpc }"&gt;
                &lt;param value="true" /&gt;
            &lt;/remotecall&gt;
        &lt;/button&gt;

        &lt;button text="pass array" onclick="this.passArray.invoke()"&gt;
            &lt;remotecall name="passArray" funcname="passClientArray" 
                        remotecontext="$once{ types_example_rpc }"&gt;
                &lt;param value="[1, 'a string', 4.5, false]" /&gt;
            &lt;/remotecall&gt;
        &lt;/button&gt;

        &lt;button text="pass hash" onclick="this.passObject.invoke()"&gt;
            &lt;remotecall name="passObject" funcname="passClientObject" 
                        remotecontext="$once{ types_example_rpc }"&gt;
                &lt;param value="{ a: 1, b: 3.14159, c: 'a string value', d: true}"&gt;
                &lt;/param&gt;
            &lt;/remotecall&gt;
        &lt;/button&gt;

    &lt;/view&gt;

&lt;/canvas&gt;
</example>

<p>The java source code used by the previous example can be found in
<tt>$LPS_HOME/WEB-INF/classes/examples</tt> and looks like:</p>

<example extract="false">
package examples;

import java.util.Vector;
import java.util.Hashtable;

public class TypesExample {

    public static String passInteger(int i) {
        return "got integer parameter: " + i;
    }

    public static String passDouble(double d) {
        return "got double parameter: " + d;
    }

    public static String passBoolean(boolean b) {
        return "got boolean parameter: " + b;
    }

    public static String passClientArray(Vector v) {
        return "got vector parameter: " + v;
    }

    public static String passClientObject(Hashtable t) {
        return "got hashtable parameter: " + t;
    }

}
</example>



<h3>Type mapping of return types from Java to JavaScript</h3>

<p>
<table border="1">
<tr><th>Server-side Java method return type</th>
    <th>Client-side JavaScript function stub return type</th></tr>
<tr><td>int/java.lang.Integer</td><td>Number+</td></tr>
<tr><td>short/java.lang.Short</td><td>Number+</td></tr>
<tr><td>long/java.lang.Long</td><td>Number+</td></tr>
<tr><td>float/java.lang.Float</td><td>Number+</td></tr>
<tr><td>double/java.lang.Double</td><td>Number+</td></tr>
<tr><td>byte/java.lang.Byte</td><td>Number+</td></tr>
<tr><td>boolean/java.lang.Boolean</td><td>Boolean</td></tr>
<tr><td>char/java.lang.Character</td><td>String</td></tr>
<tr><td>java.lang.String</td><td>String</td></tr>
<tr><td>"Array"/java.util.List*</td><td>Array</td></tr>
<tr><td>java.util.Map/java.lang.Object*</td><td>Object</td></tr>
</table>
</p>

<p><pre>
+ From "JavaScript The Definitive Guide" - O'Reilly. 

In JavaScript all numbers are floating-point numbers.

JavaScript uses the standard 8 byte IEEE floating-point numeric format, which
means the range is from:

+/- 1.7976931348623157x10^308 - very large, and +/- 5x10^-324 - very small.

As JavaScript uses floating-point numbers the accuracy is only assured for
integers between: -9,007,199,254,740,992 (-2^53) and 9,007,199,254,740,992
(2^53)
</pre></p>

<p><pre>* User-defined objects returned only contain public members. Also, the
object isn't saved anywhere in the server.</pre></p>

<example title="Java to Javascript return">
&lt;canvas debug="true" height="450" width="800"&gt;
 
    &lt;debug x="10" y="130" width="740" height="275" /&gt;

    &lt;security&gt;
        &lt;allow&gt;
            &lt;pattern&gt;^examples\.ReturnTypeExample&lt;/pattern&gt;
        &lt;/allow&gt;
    &lt;/security&gt;

    &lt;!-- See WEB-INF/classes/ReturnTypeExample.java for java source. --&gt;
    &lt;javarpc name="return_type_example_rpc" scope="none" 
             classname="examples.ReturnTypeExample"&gt;
        &lt;method event="onload"&gt;
            // Set buttons visible only after JavaRPC object loads
            canvas.buttons.setAttribute('visible', true);
        &lt;/method&gt;
        &lt;method event="ondata" args="res"&gt;
            Debug.write('(return type ondata) value:', res, ', type:', typeof(res));
        &lt;/method&gt;
        &lt;method event="onerror" args="errmsg"&gt;
            Debug.write('(return type onerror) error:', errmsg);
        &lt;/method&gt;
    &lt;/javarpc&gt;

    
    &lt;view x="10" y="10" name="buttons" visible="false" layout="spacing: 5" &gt;

        &lt;view layout="axis: x; spacing: 2" &gt;

            &lt;button text="integer" onclick="this.returnInteger.invoke()"&gt;
                &lt;remotecall funcname="returnInteger" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="integer object " onclick="this.returnIntegerObject.invoke()"&gt;
                &lt;remotecall funcname="returnIntegerObject" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="short" onclick="this.returnShort.invoke()"&gt;
                &lt;remotecall funcname="returnShort" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="short object " onclick="this.returnShortObject.invoke()"&gt;
                &lt;remotecall funcname="returnShortObject" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="long" onclick="this.returnLong.invoke()"&gt;
                &lt;remotecall funcname="returnLong" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="long object" onclick="this.returnLongObject.invoke()"&gt;
                &lt;remotecall funcname="returnLongObject" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="float" onclick="this.returnFloat.invoke()"&gt;
                &lt;remotecall funcname="returnFloat" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="float object" onclick="this.returnFloatObject.invoke()"&gt;
                &lt;remotecall funcname="returnFloatObject" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="double" onclick="this.returnDouble.invoke()"&gt;
                &lt;remotecall funcname="returnDouble" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="double object" onclick="this.returnDoubleObject.invoke()"&gt;
                &lt;remotecall funcname="returnDoubleObject" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

        &lt;/view&gt;

        &lt;view layout="axis: x; spacing: 2" &gt;

            &lt;button text="byte" onclick="this.returnByte.invoke()"&gt;
                &lt;remotecall funcname="returnByte" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="byte object" onclick="this.returnByteObject.invoke()"&gt;
                &lt;remotecall funcname="returnByteObject" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="boolean" onclick="this.returnBoolean.invoke()"&gt;
                &lt;remotecall funcname="returnBoolean" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="boolean object" onclick="this.returnBooleanObject.invoke()"&gt;
                &lt;remotecall funcname="returnBooleanObject" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="character" onclick="this.returnCharacter.invoke()"&gt;
                &lt;remotecall funcname="returnCharacter" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="character object" onclick="this.returnCharacterObject.invoke()"&gt;
                &lt;remotecall funcname="returnCharacterObject" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="string" onclick="this.returnString.invoke()"&gt;
                &lt;remotecall funcname="returnString" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="coordinate object" onclick="this.rco.invoke()"&gt;
                &lt;remotecall name="rco" funcname="returnCoordinateObject" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

        &lt;/view&gt;

        &lt;view layout="axis: x; spacing: 2" &gt;

            &lt;button text="integer array" onclick="this.returnIntegerArray.invoke()"&gt;
                &lt;remotecall funcname="returnIntegerArray" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="string array" onclick="this.returnStringArray.invoke()"&gt;
                &lt;remotecall funcname="returnStringArray" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="coordinate object array " onclick="this.returnCoordinateObjectArray.invoke()"&gt;
                &lt;remotecall funcname="returnCoordinateObjectArray" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="integer list" onclick="this.returnIntegerList.invoke()"&gt;
                &lt;remotecall funcname="returnIntegerList" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="integer map" onclick="this.rim.invoke()"&gt;
                &lt;remotecall name="rim" funcname="returnIntegerMap" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

        &lt;/view&gt;

        &lt;view layout="axis: x; spacing: 2" &gt;

            &lt;button text="coordinate object list " onclick="this.returnCoordinateObjectList.invoke()"&gt;
                &lt;remotecall funcname="returnCoordinateObjectList" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

            &lt;button text="coordinate object map" onclick="this.rcom.invoke()"&gt;
                &lt;remotecall name="rcom" funcname="returnCoordinateObjectMap" 
                            remotecontext="$once{ return_type_example_rpc }" /&gt;
            &lt;/button&gt;

        &lt;/view&gt;

    &lt;/view&gt;

&lt;/canvas&gt;
</example>

<p>The java source code used by the previous example looks like:</p>

<example extract="false">
package examples;

import java.util.List;
import java.util.Vector;
import java.util.Map;
import java.util.HashMap;

public class ReturnTypeExample {

    public static int returnInteger() {
        return 1;
    }

    public static Integer returnIntegerObject() {
        return new Integer(2);
    }

    public static short returnShort() {
        return 3;
    }

    public static Short returnShortObject() {
        return new Short((short)4);
    }

    public static long returnLong() {
        return 5;
    }

    public static Long returnLongObject() {
        return new Long(6);
    }

    public static float returnFloat() {
        return 7;
    }

    public static Float returnFloatObject() {
        return new Float(8);
    }

    public static double returnDouble() {
        return 3.14159;
    }

    public static Double returnDoubleObject() {
        return new Double(3.14159);
    }

    public static byte returnByte() {
        return (byte)11;
    }

    public static Byte returnByteObject() {
        return new Byte((byte)12);
    }

    public static boolean returnBoolean() {
        return true;
    }

    public static Boolean returnBooleanObject() {
        return new Boolean(false);
    }

    public static char returnCharacter() {
        return 'a';
    }

    public static Character returnCharacterObject() {
        return new Character('b');
    }

    public static String returnString() {
        return "returing a string";
    }

    public static Coordinate returnCoordinateObject() {
        return new Coordinate(4,2);
    }

    public static int[] returnIntegerArray() {
        int[] intarr = { 1, 2, 3, 4, 5 };
        return intarr;
    }

    public static String[] returnStringArray() {
        String[] strarr = { "one", "two", "three", "four", "five" };
        return strarr;
    }

    public static Coordinate[] returnCoordinateObjectArray() {
        Coordinate[] coarr =  { new Coordinate(1,1), 
                                new Coordinate(2,2),
                                new Coordinate(3,3),
                                new Coordinate(4,4),
                                new Coordinate(5,5) };
        return coarr;
    }

    public static List returnIntegerList() {
        List list = new Vector();
        list.add(new Integer(1));
        list.add(new Integer(2));
        list.add(new Integer(3));
        list.add(new Integer(4));
        list.add(new Integer(5));
        return list;
    }

    public static Map returnIntegerMap() {
        Map map = new HashMap();
        map.put("one", new Integer(1));
        map.put("two", new Integer(2));
        map.put("three", new Integer(3));
        map.put("four", new Integer(4));
        map.put("five", new Integer(5));
        return map;
    }

    public static List returnCoordinateObjectList() {
        List list = new Vector();
        list.add(new Coordinate(1,1));
        list.add(new Coordinate(2,2));
        list.add(new Coordinate(3,3));
        list.add(new Coordinate(4,4));
        list.add(new Coordinate(5,5));
        return list;
    }

    public static Map returnCoordinateObjectMap() {
        Map map = new HashMap();
        map.put("one", new Coordinate(1,1));
        map.put("two", new Coordinate(2,3));
        map.put("three", new Coordinate(5,8));
        map.put("four", new Coordinate(13,21));
        map.put("five", new Coordinate(34,55));
        return map;
    }

    static public class Coordinate {
        public int x;
        public int y;

        public Coordinate(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public String toString() {
            return "x: " + this.x + ", y: " + this.y;
        }
    }
}
</example>

</body>
</html>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2001-2004 Laszlo Systems, Inc.  All Rights Reserved.              *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
